AWS Lambda の arm64 アーキテクチャで Go を実行するためのカスタムランタイムを使った SAMテンプレートの紹介
Go で書いたコードを Zip形式の Lambda で実行するついでに「せっかくだから Graviton2(Arm) で動かしたいな」と思い設定方法を調べてみると Go の Lambda は arm64 をサポートしていませんでした。
代りにカスタムランタイムを用いて実行する方法がありました。試行錯誤した結果、動かすことができたので実際の設定をSAMテンプレートベースで紹介します。
- The Go gopher was designed by Renee French.
- The gopher stickers was made by Takuya Ueda.
Zip形式と、コンテナイメージ形式の違いは以下を参照ください。
なぜ
Go 1.x のランタイムの OS は Amazon Linux の提供しかないため、arm64 が使えませんでした。
Lambda ではプログラミング言語ごとにランタイムが用意されています。Python 3.9 や、Node.js 14 などなどありますが、各言語のバージョンと OS が組になって提供されています。 たとえば Python 3.7 であれば、Amazon Linux で、Python 3.9 は Amazon Linux 2 と言ったようにです。
現在、arm64 に対応している OS は Amazon Linux 2 のみです。Go 1.x のランタイムは Amazon Linux しかありませんでした。
Go 1.x などの Amazon Linux オペレーティングシステムを使用するランタイムは、arm64 アーキテクチャをサポートしません。
検証環境
以下のリンクを参考にして SAM を使って arm64 のLambda をデプロイしてみます。Amazon Linux 2 を使ったカスタムランタイムで実行してくださいといった内容です。
検証に利用したコードは以下に置いてあります。
Product | Version |
---|---|
SAM CLI | 1.37.0 |
Go | 1.17.6 |
macOS | 11.6.3 |
やってみた
arm64 対応で必要だったポイントを説明します。
重要なのは Lambda の設定を記述したtemplate.yaml
と、ビルドの設定を記述したMakefile
の2箇所だけです。
. ├── README.md ├── hello-world │ ├── Makefile │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── main_test.go ├── samconfig.toml └── template.yaml
SAMテンプレート
Go のランタイムを使うわけではないので Lambda の設定には一切 Go の文字はないです。
- Runtime で Amazon Linux 2 のイメージを指定
- Architectures でリスト形式で
arm64
を指定 - Metadata の BuildMethod で後述する
maikefile
と指定- Makefile 自体は大文字の M から始まるファイル名なので注意
AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > go-al2 Sample SAM Template for go-al2 Globals: Function: Timeout: 5 Resources: HelloWorldFunction: # Makefile 内でここの名前を指定する必要がある Type: AWS::Serverless::Function Properties: CodeUri: hello-world/ Handler: bootstrap Runtime: provided.al2 # Amazon Linux 2 ベース Architectures: [arm64] # arm64(Graviton2) 指定 Events: CatchAll: Type: Api Properties: Path: /hello Method: GET Metadata: BuildMethod: makefile # go build の設定ファイル Outputs: HelloWorldAPI: Description: "API Gateway endpoint URL for Prod environment for First Function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: "First Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
Makefile
Makefile
のファイル名は大文字のMからはじまる必要があります。テンプレートの指定では小文字はじまりのmakefile
なので気をつけてください。
build-
+ 関数名の形式でビルド対象を指定(わかりづらいので下のMakefileをご確認ください)- クロスコンパイルするために
GOOS=linux GOARCH=arm64
を指定
カスタムランタイムの構築 - AWS Serverless Application Model
build-HelloWorldFunction: GOOS=linux GOARCH=arm64 go build -o bootstrap cp ./bootstrap $(ARTIFACTS_DIR)/.
sam build & deploy
sam build
実行するとMakefile
を参照してgo build
が走ります。
$ sam build Building codeuri: /Users/hoge/github/bigmuramra/sam-sample-arm64-go/hello-world runtime: provided.al2 metadata: {'BuildMethod': 'makefile'} architecture: arm64 functions: ['HelloWorldFunction'] Running CustomMakeBuilder:CopySource Running CustomMakeBuilder:MakeBuild Current Artifacts Directory : /Users/hoge/github/bigmuramra/sam-sample-arm64-go/.aws-sam/build/HelloWorldFunction Build Succeeded
初回のデプロイであれば--guided
を付けて対話式に設定を入力してデプロイしてください。
$ sam deploy --guided
実行確認
デプロイ結果から API Gateway の URL が表示されますので、curl で GET リクエストを送ります。
----------------------------------------------------------------------------------------------------------------------------- Outputs ----------------------------------------------------------------------------------------------------------------------------- ...snip... Key HelloWorldAPI Description API Gateway endpoint URL for Prod environment for First Function Value https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/ ...snip...
以下の様にアクセス元のグローバルIPアドレスが返ってきたら成功です。
$ curl https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/ Hello, [Global IP Address]
マネジメントコンソールからデプロイされた Lambda関数を確認すると arm64 となっています。
以上、SAM を利用した arm64 対応の Go Lambda の設定方法でした。
おわりに
Lambda の Go 1.x が Amazon Linux で動いていることを知ったので試してみました。Amazon Linux はメンテナンスサポート期間(2023年8月まで)に入っているので、Lambda で Go を実行するなら arm64 で動かすかどうかは別として Amazon Linux 2 のカスタムランタイムで実行した方がよいのではないかといった感想です。カスタムランタイムの設定も一度わかってしまえば簡単でした。Lambda でなにか動かす機会があれば試してみようと思います。
Amazon Linux のサポート期限
ちなみにカスタムランタイムを使うと Rust でもなんでもやりようによって実行できます。